﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace landlord2lib
{
    public class CardGroupButterfly : CardGroup
    {
        public CardGroupButterfly(Card[] cards)
        {
            m_cards = cards;
        }

        public override bool IsValid()
        {
            try
            {
                if (m_cards.Length < 10 || m_cards.Length % 5 != 0) return false;
                foreach (Card card in m_cards) card.Reset();

                List<Card> jokerCards = new List<Card>();
                List<Card> normalCards = new List<Card>();
                foreach (Card card in m_cards)
                {
                    if (card.IsJoker) jokerCards.Add(card);
                    else normalCards.Add(card);
                }

                if (jokerCards.Count == 0) return CheckValid(normalCards);

                int[] pos = new int[jokerCards.Count];
                for (int i = 0; i < pos.Length; i++) pos[i] = (int)CardPoint.CardA;

                do
                {
                    List<Card> cards = new List<Card>(normalCards);
                    for (int i = 0; i < pos.Length; i++)
                    {
                        Card joker = jokerCards[i];
                        joker.ComparePoint = (CardPoint)pos[i];
                        cards.Add(joker);
                    }
                    if (CheckValid(cards)) return true;
                } while (EnumLevel(pos, (int)CardPoint.CardA, (int)CardPoint.Card3));
                return false;
            }
            catch
            {
                return false;
            }
        }

        private bool EnumLevel(int[] pos, int max, int min)
        {
            pos[0]--;
            if (pos[0] < min)
            {
                if (pos.Length < 2) return false;
                pos[0] = max;
                pos[1]--;
                if (pos[1] < min)
                {
                    if (pos.Length < 3) return false;
                    pos[1] = max;
                    pos[2]--;
                    if (pos[2] < min)
                    {
                        if (pos.Length < 4) return false;
                        pos[2] = max;
                        pos[3]--;
                        if (pos[3] < min) return false;
                    }
                }
            }
            return true;
        }

        private bool CheckValid(List<Card> cards)
        {
            try
            {
                List<Card>[] normalCards = new List<Card>[(int)CardPoint.CardA + 1];
                foreach (Card card in cards)
                {
                    if (normalCards[(int)card.ComparePoint] == null) normalCards[(int)card.ComparePoint] = new List<Card>();
                    normalCards[(int)card.ComparePoint].Add(card);
                }
                int tripleStart = 99, tripleEnd = -1, tripleCount = 0;
                int pairStart = 99, pairEnd = -1, pairCount = 0;
                int tripleLast = -1, pairLast = -1;
                for (int i = 0; i < normalCards.Length; i++)
                {
                    if (normalCards[i] == null) continue;
                    if (normalCards[i].Count == 3)
                    {
                        if (tripleStart > i) tripleStart = i;
                        if (tripleEnd < i) tripleEnd = i;
                        tripleCount++;
                        if (tripleLast < 0) tripleLast = i;
                        else
                        {
                            if (i - tripleLast > 1) return false;
                            tripleLast = i;
                        }
                    }
                    else if (normalCards[i].Count == 2)
                    {
                        if (pairStart > i) pairStart = i;
                        if (pairEnd < i) pairEnd = i;
                        pairCount++;
                        if (pairLast < 0) pairLast = i;
                        else
                        {
                            if (i - pairLast > 1) return false;
                            pairLast = i;
                        }
                    }
                    else return false;
                }
                return tripleCount >= 2 && pairCount >= 2 && tripleCount == pairCount;
            }
            catch
            {
                return false;
            }
        }

        public override int CompareTo(CardGroup other)
        {
            try
            {
                if (other is CardGroupButterfly)
                {
                    CardGroupButterfly o = (CardGroupButterfly)other;
                    if (m_cards.Length != o.m_cards.Length) return -1;
                    return GetCompareCard().CompareTo(o.GetCompareCard());
                }
                else return -1;
            }
            catch
            {
                return 0;
            }
        }

        private Card GetCompareCard()
        {
            List<Card>[] normalCards = new List<Card>[(int)CardPoint.CardA + 1];
            foreach (Card card in m_cards)
            {
                if (normalCards[(int)card.ComparePoint] == null) normalCards[(int)card.ComparePoint] = new List<Card>();
                normalCards[(int)card.ComparePoint].Add(card);
            }
            for (int i = normalCards.Length - 1; i >= 0; i--)
            {
                if (normalCards[i] == null) continue;
                if (normalCards[i].Count == 3) return normalCards[i][0];
            }
            return null;
        }
    }
}
